package gen

import (
	"app/config"
	"errors"
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gen"
	"gorm.io/gorm"
)

func Models(group string, args ...string) (err error) {
	//查看是否存在分组配置
	if _, ok := config.Config.Database[group]; !ok {
		return errors.New("不存在的数据库配置：" + args[1])
	}
	//如果数据库目录不区分想放在一起可以改下面的OutPath去掉group
	g := gen.NewGenerator(gen.Config{
		OutPath:           fmt.Sprintf("./internal/gen/%s/query", group), // output directory, default value is ./query
		Mode:              gen.WithDefaultQuery | gen.WithQueryInterface,
		FieldNullable:     true,  // 如果希望可为空字段生成属性为指针类型，请将 FieldNullable 设置为 true
		FieldCoverable:    true,  // 如果要分配在“创建”API 中具有默认值的字段，请将 FieldCoverable 设置为 true
		FieldSignable:     true,  // 如果要生成具有无符号整数类型的字段，请将字段可签名设置为 true
		FieldWithIndexTag: true,  // 如果要从数据库生成索引标记，请将 FieldWithIndexTag 设置为 true
		FieldWithTypeTag:  true,  // 如果要从数据库生成类型标记，请将 FieldWithTypeTag 设置为 true
		WithUnitTest:      false, // if you need unit tests for query code, set WithUnitTest true
	})

	softDeleteField := gen.FieldType("delete_time", "soft_delete.DeletedAt")
	// 模型自定义选项组
	fieldOpts := []gen.ModelOpt{softDeleteField}

	g.UseDB(connect(group))

	g.WithDataTypeMap(dataMap)

	g.ApplyBasic(g.GenerateAllTable(fieldOpts...)...) //生成全表

	g.Execute()
	return
}

// 指定model属性类型和 db 字段类型之间的映射关系。
var dataMap = map[string]func(gorm.ColumnType) (dataType string){
	// int mapping
	"tinyint":   func(columnType gorm.ColumnType) (dataType string) { return "int64" },
	"smallint":  func(columnType gorm.ColumnType) (dataType string) { return "int64" },
	"mediumint": func(columnType gorm.ColumnType) (dataType string) { return "int64" },
	"int":       func(columnType gorm.ColumnType) (dataType string) { return "int64" },
	"bigint":    func(columnType gorm.ColumnType) (dataType string) { return "int64" },
}

// 连接数据库
func connect(dsn string) *gorm.DB {
	c := config.Config.Database[dsn]
	var db *gorm.DB
	var err error
	switch c.Type {
	case "mysql":
		// Initialize a *gorm.DB instance
		if db, err = gorm.Open(mysql.Open(c.Dsn)); err != nil {
			panic("数据库连接失败：" + err.Error())
		}
	default:
		panic("不持支的数据库类型" + c.Type)
	}
	return db
}
